/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */

package l1j.server.server.clientpackets;

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.Server.L1World.L1World;
import l1j.opqlo.Server.L1World.WorldClan;
import l1j.opqlo.Server.L1World.WorldWar;
import l1j.opqlo.Timer.Controler.Server.ServerWarExecutor;
import l1j.server.Config;//TODO 調整能力值上限
import l1j.server.echo.ClientThread;
import l1j.server.server.datatables.CharacterTable;
import l1j.server.server.datatables.DecomposeTable;
import l1j.server.server.datatables.HouseTable;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.datatables.PetTable;
import l1j.server.server.datatables.lock.ClanEmblemReading;
import l1j.server.server.datatables.lock.ClanReading;
import l1j.server.server.model.L1CastleLocation;
import l1j.server.server.model.L1Character;
import l1j.server.server.model.L1ChatParty;
import l1j.server.server.model.L1Clan;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.L1Party;
import l1j.server.server.model.L1PcInventory;
import l1j.server.server.model.L1Quest;
import l1j.server.server.model.L1Teleport;
import l1j.server.server.model.L1War;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.Instance.L1PetInstance;
import l1j.server.server.model.item.L1ItemId;
import l1j.server.server.model.map.L1Map;
import l1j.server.server.serverpackets.S_ChangeName;
import l1j.server.server.serverpackets.S_CharTitle;
import l1j.server.server.serverpackets.S_CharVisualUpdate;
import l1j.server.server.serverpackets.S_OwnCharStatus2;
import l1j.server.server.serverpackets.S_PacketBox;
import l1j.server.server.serverpackets.S_Resurrection;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SkillSound;
import l1j.server.server.serverpackets.S_SystemMessage;//TODO 調整能力值上限
import l1j.server.server.serverpackets.S_Trade;
import l1j.server.server.templates.L1Decompose;
import l1j.server.server.templates.L1House;
import l1j.server.server.templates.L1Npc;
import l1j.server.server.templates.L1Pet;
import l1j.server.server.utils.Random;

public class C_Attr extends ClientBasePacket {

	private static final Logger _log = Logger.getLogger(C_Attr.class.getName());
	private static final String C_ATTR = "[C] C_Attr";

	private static final int HEADING_TABLE_X[] = { 0, 1, 1, 1, 0, -1, -1, -1 };

	private static final int HEADING_TABLE_Y[] = { -1, -1, 0, 1, 1, 1, 0, -1 };

	private static void renamePet(L1PetInstance pet, String name) {
//		if (pet == null || name == null) {
//			throw new NullPointerException();
//		}

		final int petItemObjId = pet.getItemObjId();
		final L1Pet petTemplate = PetTable.getInstance().getTemplate(petItemObjId);
		if (petTemplate == null) {
			throw new NullPointerException();
		}

		final L1PcInstance pc = (L1PcInstance) pet.getMaster();
		if (PetTable.isNameExists(name)) {
			pc.sendPackets(new S_ServerMessage(327)); // 同じ名前がすでに存在しています。
			return;
		}
		final L1Npc l1npc = NpcTable.getInstance().getTemplate(pet.getNpcId());
		if (!pet.getName().equalsIgnoreCase(l1npc.get_name())) {
			pc.sendPackets(new S_ServerMessage(326)); // 一度決めた名前は変更できません。
			return;
		}
		pet.setName(name);
		petTemplate.set_name(name);
		PetTable.getInstance().storePet(petTemplate); // DBに書き込み
		final L1ItemInstance item = pc.getInventory().getItem(pet.getItemObjId());
		pc.getInventory().updateItem(item);
		pc.sendPackets(new S_ChangeName(pet.getId(), name));
		pc.broadcastPacketAll(new S_ChangeName(pet.getId(), name));
	}

	private void callClan(L1PcInstance pc) {
		final L1PcInstance callClanPc = (L1PcInstance) L1World.getInstance()
				.findObject(pc.getTempID());
		pc.setTempID(0);
		if (callClanPc == null) {
			return;
		}
		if (!pc.getMap().isEscapable() && !pc.isGm()) {
			// 這附近的能量影響到瞬間移動。在此地無法使用瞬間移動。
			pc.sendPackets(new S_ServerMessage(647));
			L1Teleport.teleport(pc, pc.getLocation(), pc.getHeading(), false);
			return;
		}
		if (pc.getId() != callClanPc.getCallClanId()) {
			return;
		}

		boolean isInWarArea = false;
		final int castleId = L1CastleLocation.getCastleIdByArea(callClanPc);
		if (castleId != 0) {
			isInWarArea = true;
			if (ServerWarExecutor.get().isNowWar(castleId)) {
				isInWarArea = false; // 戰爭也可以在時間的旗
			}
		}
		final short mapId = callClanPc.getMapId();
		if (mapId != 0 && mapId != 4 && mapId != 304 || isInWarArea) {
			// 沒有任何事情發生。
			pc.sendPackets(new S_ServerMessage(79));
			return;
		}

		final L1Map map = callClanPc.getMap();
		int locX = callClanPc.getX();
		int locY = callClanPc.getY();
		int heading = callClanPc.getCallClanHeading();
		locX += HEADING_TABLE_X[heading];
		locY += HEADING_TABLE_Y[heading];
		heading = (heading + 4) % 4;

		boolean isExsistCharacter = false;
		for (final L1Object object : L1World.getInstance().getVisibleObjects(
				callClanPc, 1)) {
			if (object instanceof L1Character) {
				final L1Character cha = (L1Character) object;
				if (cha.getX() == locX && cha.getY() == locY
						&& cha.getMapId() == mapId) {
					isExsistCharacter = true;
					break;
				}
			}
		}
		if (locX == 0 && locY == 0 || !map.isPassable(locX, locY)
				|| isExsistCharacter) {
			// 因你要去的地方有障礙物以致於無法直接傳送到該處。
			pc.sendPackets(new S_ServerMessage(627));
			return;
		}
		L1Teleport.teleport(pc, locX, locY, mapId, heading, true,L1Teleport.CALL_CLAN);
	}

	private void changeClan(ClientThread clientthread, L1PcInstance pc, L1PcInstance joinPc, int maxMember) {
		final int clanId = pc.getClanid();
		final String clanName = pc.getClanname();
		final L1Clan clan = WorldClan.get().getClan(clanName);
		final String clanMemberName[] = clan.getAllMembers();
		final int clanNum = clanMemberName.length;

		final int oldClanId = joinPc.getClanid();
		final String oldClanName = joinPc.getClanname();
		final L1Clan oldClan = WorldClan.get().getClan(oldClanName);
		final String oldClanMemberName[] = oldClan.getAllMembers();
		final int oldClanNum = oldClanMemberName.length;
		if (clan != null && oldClan != null && joinPc.isCrown() && joinPc.getId() == oldClan.getLeaderId()) {// 自分が君主
			if (maxMember < clanNum + oldClanNum) { // 空きがない
				joinPc.sendPackets( new S_ServerMessage(188, pc.getName()));// %0はあなたを血盟員として受け入れることができません。
				return;
			}
			final L1PcInstance clanMember[] = clan.getOnlineClanMember();
			for (final L1PcInstance element : clanMember) {
				element.sendPackets(new S_ServerMessage(94, joinPc.getName())); // \f1%0が血盟の一員として受け入れられました。
			}

			for (final String element : oldClanMemberName) {
				final L1PcInstance oldClanMember = L1World.getInstance().getPlayer(element);
				if (oldClanMember != null) { // オンライン中の旧クランメンバー
					oldClanMember.setClanid(clanId);
					oldClanMember.setClanname(clanName);
					// 血盟連合に加入した君主はガーディアン
					// 君主が連れてきた血盟員は見習い
					if (oldClanMember.getId() == joinPc.getId()) {
						oldClanMember.setClanRank(L1Clan.CLAN_RANK_GUARDIAN);
					} else {
						//						oldClanMember.setClanRank(L1Clan.CLAN_RANK_PROBATION);
						oldClanMember.setClanRank(L1Clan.CLAN_RANK_PUBLIC);
					}
					try {
						oldClanMember.save();// DBにキャラクター情報を書き込む
					} catch (final Exception e) {
						_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
					}
					clan.addMemberName(oldClanMember.getName());
					oldClanMember.sendPackets(new S_ServerMessage(95, clanName)); // \f1%0血盟に加入しました。
				} else { // オフライン中の旧クランメンバー
					try {
						final L1PcInstance offClanMember = CharacterTable.getInstance().restoreCharacter(element);
						offClanMember.setClanid(clanId);
						offClanMember.setClanname(clanName);
						//						offClanMember.setClanRank(L1Clan.CLAN_RANK_PROBATION);
						offClanMember.setClanRank(L1Clan.CLAN_RANK_PUBLIC);
						offClanMember.save(); // DBにキャラクター情報を書き込む
						clan.addMemberName(offClanMember.getName());
					} catch (final Exception e) {
						_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
					}
				}
			}
			// 資料刪除
			ClanEmblemReading.get().deleteIcon(oldClanId);
			/*final String emblem_file = String.valueOf(oldClanId);
						final File file = new File("emblem/" + emblem_file);
						file.delete();*/
			ClanReading.get().deleteClan(oldClanName);
		}
	}

	@Override
	public String getType() {
		return C_ATTR;
	}

	@Override
	public void start(final byte[] decrypt, final ClientThread client) {
		try {
			// 資料載入
			this.read(decrypt);

			final L1PcInstance pc = client.getActiveChar();

			if (pc.isGhost()) { // 鬼魂模式
				return;
			}

			if (pc.isTeleport()) { // 傳送中
				return;
			}

			//			final int i = this.readH();//TODO 3.51C未知的功能
			//			final
			////			int MessageNumber = 0;//TODO 3.51 YN 訊息處理編序(尚無操作碼只是先定義&需要在測試)
			//
			//			/*	if (i == 0) {
			//			MessageNumber = readD();//TODO 3.51 C封包還需要在測試
			//			i = readH();
			//		}*/
			//			int attrcode;
			//			if (i == 479) {
			//				attrcode = i;
			//			} else {
			//				@SuppressWarnings("unused")
			//				final
			//				int count = this.readD(); // 紀錄世界中發送YesNo的次數
			//				attrcode = this.readH();
			//			}

			int attrcode = readH();
			@SuppressWarnings("unused")
			int tgobjid = 0;

			if (attrcode == 0) {
				tgobjid = readD();
				attrcode = readH();
			}

			int c;
			String name;
			//				System.out.println(attrcode);
			switch (attrcode) {
			case 97: // %0が血盟に加入したがっています。承諾しますか？（Y/N）
				c = this.readC();
				final L1PcInstance joinPc = (L1PcInstance) L1World.getInstance().findObject(pc.getTempID());
				pc.setTempID(0);
				if (joinPc != null) {
					if (c == 0) { // No
						joinPc.sendPackets(new S_ServerMessage(96, pc.getName())); // \f1%0はあなたの要請を拒絶しました。
					} else if (c == 1) { // Yes
						final int clan_id = pc.getClanid();
						final String clanName = pc.getClanname();
						final L1Clan clan = WorldClan.get().getClan(clanName);
						if (clan != null) {
							int maxMember = 0;
							final int charisma = pc.getCha();
							boolean lv45quest = false;
							if (pc.getQuest().isEnd(L1Quest.QUEST_LEVEL45)) {
								lv45quest = true;
							}
							if (pc.getLevel() >= 50) { // Lv50以上
								if (lv45quest == true) { // Lv45クエストクリア済み
									maxMember = charisma * 9;
								} else {
									maxMember = charisma * 3;
								}
							} else { // Lv50未満
								if (lv45quest == true) { // Lv45クエストクリア済み
									maxMember = charisma * 6;
								} else {
									maxMember = charisma * 2;
								}
							}
							if (Config.MAX_CLAN_MEMBER > 0) {
								maxMember = Config.MAX_CLAN_MEMBER;// Clan人数の上限の設定あり
							}

							if (joinPc.getClanid() == 0) { final String clanMembersName[] = clan.getAllMembers();// クラン未加入
							if (maxMember <= clanMembersName.length) { // 空きがない
								joinPc.sendPackets( new S_ServerMessage(188, pc.getName()));// %0はあなたを血盟員として受け入れることができません。
								return;
							}
							for (final L1PcInstance clanMembers : clan.getOnlineClanMember()) {
								clanMembers.sendPackets(new S_ServerMessage(94,joinPc.getName())); // \f1%0が血盟の一員として受け入れられました。
							}
							joinPc.setClanid(clan_id);
							joinPc.setClanname(clanName);
							joinPc.setClanRank(L1Clan.CLAN_RANK_PUBLIC);
							joinPc.setTitle("");
							joinPc.sendPackets(new S_CharTitle(joinPc.getId(),""));
							joinPc.broadcastPacketAll(new S_CharTitle(joinPc.getId(), ""));
							joinPc.save(); // DBにキャラクター情報を書き込む
							clan.addMemberName(joinPc.getName());
							joinPc.sendPackets(new S_ServerMessage(95, clanName)); // \f1%0血盟に加入しました。
							} else { // クラン加入済み（クラン連合）
								if (Config.CLAN_ALLIANCE) {
									this.changeClan(client, pc, joinPc, maxMember);
								} else {
									joinPc.sendPackets(new S_ServerMessage(89)); // \f1あなたはすでに血盟に加入しています。
								}
							}
						}
					}
				}
				break;

			case 217: // %0血盟の%1があなたの血盟との戦争を望んでいます。戦争に応じますか？（Y/N）
			case 221: // %0血盟が降伏を望んでいます。受け入れますか？（Y/N）
			case 222: // %0血盟が戦争の終結を望んでいます。終結しますか？（Y/N）
				c = this.readC();
				final L1PcInstance enemyLeader = (L1PcInstance) L1World.getInstance().findObject(pc.getTempID());
				if (enemyLeader == null) {
					return;
				}
				pc.setTempID(0);
				final String clanName = pc.getClanname();
				final String enemyClanName = enemyLeader.getClanname();
				if (c == 0) { // No
					if (attrcode == 217) {
						enemyLeader.sendPackets(new S_ServerMessage(236, clanName)); // %0血盟があなたの血盟との戦争を拒絶しました。
					} else if (attrcode == 221 || attrcode == 222) {
						enemyLeader.sendPackets(new S_ServerMessage(237, clanName)); // %0血盟があなたの提案を拒絶しました。
					}
				} else if (c == 1) { // Yes
					if (attrcode == 217) {
						final L1War war = new L1War();
						war.handleCommands(2, enemyClanName, clanName); // 模擬戦開始
					} else if (attrcode == 221 || attrcode == 222) {
						// 取回全部戰爭清單
						for (final L1War war : WorldWar.get().getWarList()) {
							if (war.checkClanInWar(clanName)) { // 戰爭中
								if (attrcode == 221) {
									war.surrenderWar(enemyClanName, clanName); // 投降

								} else if (attrcode == 222) {
									war.ceaseWar(enemyClanName, clanName); // 結束
								}
								break;
							}
						}
					}
				}
				break;

			case 252: // %0%sがあなたとアイテムの取引を望んでいます。取引しますか？（Y/N）
				c = this.readC();
				final L1Object findobj = L1World.getInstance().findObject(pc.getTradeID());
				if(findobj != null){

					if(findobj instanceof L1PcInstance){
						final L1PcInstance trading_partner = (L1PcInstance)findobj;
						if (trading_partner != null) {
							if (c == 0){ // No
								trading_partner.sendPackets(new S_ServerMessage(253, pc.getName())); // %0%dはあなたとの取引に応じませんでした。
								pc.setTradeID(0);
								trading_partner.setTradeID(0);
							} else if (c == 1){ // Yes
								pc.sendPackets(new S_Trade(trading_partner.getName()));
								L1World.getInstance().addTradeInventory(pc.getId()).setPartnerId(trading_partner.getId());;//新增交易背包---自己
								trading_partner.sendPackets(new S_Trade(pc.getName()));
								L1World.getInstance().addTradeInventory(trading_partner.getId()).setPartnerId(pc.getId());//新增交易背包---對方
							}
						}
					}
				}
				break;

			case 321: // また復活したいですか？（Y/N）
				c = this.readC();
				final L1PcInstance resusepc1 = (L1PcInstance) L1World.getInstance().findObject(pc.getTempID());
				pc.setTempID(0);
				if (resusepc1 != null) { // 復活スクロール
					if (c == 0) { // No
						;
					} else if (c == 1) { // Yes
						pc.sendPacketsX10(new S_SkillSound(pc.getId(), '\346'));
						// pc.resurrect(pc.getLevel());
						// pc.setCurrentHp(pc.getLevel());
						pc.resurrect(pc.getMaxHp() / 2);
						pc.setCurrentHp(pc.getMaxHp() / 2);
						pc.startHpRegeneration();
						pc.startMpRegeneration();
						pc.startMpRegenerationByDoll();
						pc.startHpRegenerationByDoll();
						//					pc.setDeleTime(0);//opqlo 角色死亡踢除計時
						pc.stopPcDeleteTimer();
						pc.sendPacketsX10(new S_Resurrection(pc, resusepc1, 0));
						pc.sendPacketsX10(new S_CharVisualUpdate(pc));
					}
				}
				break;

			case 322: // また復活したいですか？（Y/N）
				c = this.readC();
				final L1PcInstance resusepc2 = (L1PcInstance) L1World.getInstance().findObject(pc.getTempID());
				pc.setTempID(0);
				if (resusepc2 != null) { // 祝福された 復活スクロール、リザレクション、グレーター リザレクション
					if (c == 0) { // No
					} else if (c == 1) { // Yes
						pc.sendPacketsX10(new S_SkillSound(pc.getId(), '\346'));
						pc.resurrect(pc.getMaxHp());
						pc.setCurrentHp(pc.getMaxHp());
						pc.startHpRegeneration();
						pc.startMpRegeneration();
						pc.startMpRegenerationByDoll();
						//					pc.setDeleTime(0);//opqlo 角色死亡踢除計時
						pc.stopPcDeleteTimer();
						pc.sendPacketsX10(new S_Resurrection(pc, resusepc2, 0));
						pc.sendPacketsX10(new S_CharVisualUpdate(pc));
						// EXPロストしている、G-RESを掛けられた、EXPロストした死亡
						// 全てを満たす場合のみEXP復旧
						if (pc.getExpRes() == 1 && pc.isGres() && pc.isGresValid()) {
							pc.resExp();
							pc.setExpRes(0);
							pc.setGres(false);
						}
					}
				}
				break;

			case 325: // 動物の名前を決めてください：
				c = this.readC();
				name = this.readS();
				if(name == null){
					return;
				}
				final L1PetInstance pet = (L1PetInstance) L1World.getInstance().findObject(pc.getTempID());
				pc.setTempID(0);
				if(pet !=null && name !=null){
					renamePet(pet, name);
				}
				break;

			case 512: // 家の名前は？
				c = this.readC();
				name = this.readS();
				if(name == null){
					return;
				}
				final int houseId = pc.getTempID();
				pc.setTempID(0);
				if (name.length() <= 16) {
					final L1House house = HouseTable.getInstance().getHouseTable(houseId);
					house.setHouseName(name);
					HouseTable.getInstance().updateHouse(house); // DBに書き込み
				} else {
					pc.sendPackets(new S_ServerMessage(513)); // 家の名前が長すぎます。
				}
				break;

			case 630: // %0%sがあなたと決闘を望んでいます。応じますか？（Y/N）
				c = this.readC();
				final L1PcInstance fightPc = (L1PcInstance) L1World.getInstance().findObject(pc.getFightId());
				if (c == 0) {
					pc.setFightId(0);
					fightPc.setFightId(0);
					fightPc.sendPackets(new S_ServerMessage(631, pc.getName())); // %0%dがあなたとの決闘を断りました。
				} else if (c == 1) {
					fightPc.sendPackets(new S_PacketBox(S_PacketBox.MSG_DUEL,fightPc.getFightId(), fightPc.getId()));
					pc.sendPackets(new S_PacketBox(S_PacketBox.MSG_DUEL, pc.getFightId(), pc.getId()));
				}
				break;

			case 653: // 離婚をするとリングは消えてしまいます。離婚を望みますか？（Y/N）
				c = this.readC();
				final L1PcInstance target653 = (L1PcInstance) L1World.getInstance().findObject(pc.getPartnerId());
				if (c == 0) { // No
					return;
				} else if (c == 1) { // Yes
					if (target653 != null) {
						target653.setPartnerId(0);
						target653.save();
						target653.sendPackets(new S_ServerMessage(662)); // \f1あなたは結婚していません。
					} else {
						CharacterTable.updatePartnerId(pc.getPartnerId());
					}
				}
				pc.setPartnerId(0);
				pc.save(); // DBにキャラクター情報を書き込む
				pc.sendPackets(new S_ServerMessage(662)); // \f1あなたは結婚していません。
				break;

			case 654: // %0%sあなたと結婚したがっています。%0と結婚しますか？（Y/N）
				c = this.readC();
				final L1PcInstance partner = (L1PcInstance) L1World.getInstance().findObject(pc.getTempID());
				pc.setTempID(0);
				if (partner != null) {
					if (c == 0) { // No
						partner.sendPackets(new S_ServerMessage( 656, pc.getName()));// %0%sはあなたとの結婚を拒絶しました。
					} else if (c == 1) { // Yes
						pc.setPartnerId(partner.getId());
						pc.save();
						pc.sendPackets(new S_ServerMessage(790));// 皆の祝福の中で、二人の結婚が行われました。
						pc.sendPackets(new S_ServerMessage(655, partner.getName()));// おめでとうございます！%0と結婚しました。
						partner.setPartnerId(pc.getId());
						partner.save();
						L1World.getInstance().broadcastServerMessage("恭喜!!" + partner.getName() + "和" + pc.getName() + "的婚禮在所有人的祝福下完成");
					}
				}
				break;

				// コールクラン
			case 729: // 君主が呼んでいます。召喚に応じますか？（Y/N）
				c = this.readC();
				if (c == 0) { // No
					;
				} else if (c == 1) { // Yes
					this.callClan(pc);
				}
				break;

			case 738: // 経験値を回復するには%0のアデナが必要です。経験値を回復しますか？
				c = this.readC();
				if (c == 0) { // No
				} else if (c == 1 && pc.getExpRes() == 1) { // Yes
					int cost = 0;
					final int level = pc.getLevel();
					final int lawful = pc.getLawful();
					if (level < 45) {
						cost = level * level * 100;
					} else {
						cost = level * level * 200;
					}
					if (lawful >= 0) {
						cost = cost / 2;
					}
					if (pc.getInventory().consumeItem(L1ItemId.ADENA, cost)) {
						pc.resExp();
						pc.setExpRes(0);
					} else {
						pc.sendPackets(new S_ServerMessage(189)); // \f1アデナが不足しています。
					}
				}
				break;

			case 951: // チャットパーティー招待を許可しますか？（Y/N）
				c = this.readC();
				final L1PcInstance chatPc = (L1PcInstance) L1World.getInstance().findObject(pc.getPartyID());
				if (chatPc != null) {
					if (c == 0) { // No
						chatPc.sendPackets(new S_ServerMessage(423, pc.getName())); // %0が招待を拒否しました。
						pc.setPartyID(0);
					} else if (c == 1) { // Yes
						if (chatPc.isInChatParty()) {
							if (chatPc.getChatParty().isVacancy() || chatPc.isGm()) {
								chatPc.getChatParty().addMember(pc);
							} else {
								chatPc.sendPackets(new S_ServerMessage(417)); // これ以上パーティーメンバーを受け入れることはできません。
							}
						} else {
							final L1ChatParty chatParty = new L1ChatParty();
							chatParty.addMember(chatPc);
							chatParty.addMember(pc);
							chatPc.sendPackets(new S_ServerMessage(424, pc.getName())); // %0がパーティーに入りました。
						}
					}
				}
				break;

			case 953: // パーティー招待を許可しますか？（Y/N）
				c = this.readC();
				final L1PcInstance target = (L1PcInstance) L1World.getInstance().findObject(pc.getPartyID());
				if (target != null) {
					if (c == 0) // No
					{
						target.sendPackets(new S_ServerMessage(423, pc.getName())); // %0が招待を拒否しました。
						pc.setPartyID(0);
					} else if (c == 1) // Yes
					{
						if (target.isInParty()) {
							// 招待主がパーティー中
							if (target.getParty().isVacancy() || target.isGm()) {
								// パーティーに空きがある
								target.getParty().addMember(pc);
							} else {
								// パーティーに空きがない
								target.sendPackets(new S_ServerMessage(417)); // これ以上パーティーメンバーを受け入れることはできません。
							}
						} else {
							// 招待主がパーティー中でない
							final L1Party party = new L1Party();
							party.addMember(target);
							party.addMember(pc);
							target.sendPackets(new S_ServerMessage(424, pc.getName())); // %0がパーティーに入りました。
						}
					}
				}
				break;

			case 479: // どの能力值を向上させますか？（str、dex、int、con、wis、cha）
				if (this.readC() == 1) {
					final String s = this.readS();
					if(s == null){
						return;
					}
					if (!(pc.getLevel() - 50 > pc.getBonusStats())) {
						return;
					}
					if (s.toLowerCase().equals("str".toLowerCase())) {
						if (pc.getBaseStr() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseStr((byte) 1); //素STR值+1
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					} else if (s.toLowerCase().equals("dex".toLowerCase())) {
						if (pc.getBaseDex() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseDex((byte) 1); //素DEX值+1
							pc.resetBaseAc();
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					} else if (s.toLowerCase().equals("con".toLowerCase())) {
						if (pc.getBaseCon() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseCon((byte) 1); //素CON值+1
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					} else if (s.toLowerCase().equals("int".toLowerCase())) {
						if (pc.getBaseInt() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseInt((byte) 1); //素INT值+1
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					} else if (s.toLowerCase().equals("wis".toLowerCase())) {
						if (pc.getBaseWis() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseWis((byte) 1); //素WIS值+1
							pc.resetBaseMr();
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					} else if (s.toLowerCase().equals("cha".toLowerCase())) {
						if (pc.getBaseCha() < Config.BONUS_STATS1) {// TODO 調整能力值上限
							pc.addBaseCha((byte) 1); //素CHA值+1
							pc.setBonusStats(pc.getBonusStats() + 1);
							pc.sendPackets(new S_OwnCharStatus2(pc));
							pc.sendPackets(new S_CharVisualUpdate(pc));
							pc.save(); // DB情報書迂
						} else {
							pc.sendPackets(new S_SystemMessage("你的能力值已達到上限請選擇其他能力值。"));
						}
					}
				}
				break;

			case 768:
				c = this.readC();
				if (c  == 1) {
					final L1PcInventory inv = pc.getInventory();
					final L1ItemInstance[] itemList = inv.get轉移卷軸();
					if(itemList[0]!=null && itemList[1]!=null
							&&inv.checkItem(itemList[0]) &&inv.checkItem(itemList[1])){
						final L1ItemInstance scroll = itemList[0] ,  item = itemList[1];
						if(scroll.getItemId()==780046 && item.getItem().getType2()==1//	武器強化轉移卷
								||scroll.getItemId()==780047 && item.getItem().getType2()==2 ){//	防具強化轉移卷
							if(pc.getInventory().checkEquipped(item.getItemId())){
								pc.getInventory().setEquipped(item, false);
							}
							item.setEnchantLevel(scroll.getChargeCount());
							inv.updateItem(item, L1PcInventory.COL_ENCHANTLVL);
							inv.saveItem(item, L1PcInventory.COL_ENCHANTLVL);
							inv.removeItem(scroll);
						}else{
							pc.sendPackets(new S_ServerMessage(79));
						}
					}else if(pc._DECOMPSET_ITEMID >0){
						final L1Object obj =L1World.getInstance().findObject(pc._DECOMPSET_ITEMID);
						if(obj instanceof L1ItemInstance){
							final L1ItemInstance item = (L1ItemInstance)obj;
							if(inv.checkItem(item)){
								inv.removeItem(item, 1);
								ArrayList<L1Decompose>list = DecomposeTable.get().getList(item.getItemId());
								if(list != null){
									for(final L1Decompose temp : list){
										final int newitemid = temp.getItem(Random.nextInt(100)+1);
										if(newitemid >0){
											createNewItem(pc,newitemid , temp.getCount());
										}
									}
									list.clear();
								}else{
									pc.sendPackets(new S_ServerMessage(79));
								}
							}else{
								pc.sendPackets(new S_ServerMessage(79));
							}
						}else{
							pc.sendPackets(new S_ServerMessage(79));
						}
					}else{
						pc.sendPackets(new S_ServerMessage(79));
					}
				}
				pc._DECOMPSET_ITEMID = 0;
				pc.getInventory().remove轉移卷軸();
				break;
			default:
				break;
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);

		} finally {
			this.over();
		}
	}
	private boolean createNewItem(L1PcInstance pc,final int item_id,final int count) {
		L1ItemInstance item = ItemTable.getInstance().createItem(item_id);
		if (item != null) {
			item.setCount(count);
			//			if (pc.getInventory().checkAddItem(item, count) == L1Inventory.OK) {
			pc.getInventory().storeItem(item);
			pc.sendPackets(new S_ServerMessage(403, item.getLogName())); // %0を手に入れました。
			return true;
			//			} else { // 持てない場合は地面に落とす 處理のキャンセルはしない（不正防止）
			//				//L1World.getInstance().getInventory(pc.getX(), pc.getY(), pc.getMapId()).storeItem(item);
			//				return false;
			//			}
		} else {
			return false;
		}
	}
}